package com.loe.ktui.ui

import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.FrameLayout
import android.widget.LinearLayout
import com.google.android.flexbox.FlexboxLayout
import com.loe.ktui.*
import com.loe.ktui.setDelayClickListener
import com.loe.ktui.util.KtCornerProvider
import com.loe.ktui.util.UiShape

/**
 * Ui基类
 *
 * @author 章路顺
 * @since 2022/9/30-15:27
 */
open class UiView(var id: String? = null)
{
    open var width: Any? = null
    open var height: Any? = null
    open var layoutGravity: Int? = Gravity.LEFT
    open var weight: Double? = null
    open var margin: Any? = null
    open var marginH: Any? = null
    open var marginV: Any? = null
    open var marginLeft: Any? = null
    open var marginTop: Any? = null
    open var marginRight: Any? = null
    open var marginBottom: Any? = null

    open var bg: Any? = null
    open var padding: Any? = null
    open var paddingH: Any? = null
    open var paddingV: Any? = null
    open var paddingLeft: Any? = null
    open var paddingTop: Any? = null
    open var paddingRight: Any? = null
    open var paddingBottom: Any? = null
    open var transZ: Any? = null
    open var alpha: Double? = null
    open var scaleX: Double? = null
    open var scaleY: Double? = null
    open var rotation: Double? = null
    open var visible: Boolean? = null
    open var focus: Boolean? = null
    open var corner: Any? = null
    open var cornerDirect: String? = null
    open var minWidth: Any? = null
    open var minHeight: Any? = null
    open var link: String? = null

    open var alignSelf: Int? = null
    open var flexGrow: Double? = null
    open var flexShrink: Double? = null
    open var flexBasisPercent: Double? = null
    open var isWrapBefore: Boolean? = null
    open var maxHeight: Any? = null
    open var maxWidth: Any? = null
    open var order: Int? = null

    open var isClick: Boolean? = null

    open var onClick: (View.() -> Unit)? = null
    open fun onClick(onClick: View.() -> Unit)
    {
        this.onClick = onClick
    }

    open var delayClick: (View.() -> Unit)? = null
    open fun delayClick(delayClick: View.() -> Unit)
    {
        this.delayClick = delayClick
    }

    open var onCreateView: (View.() -> Unit)? = null
    open fun onCreateView(onCreateView: (View.() -> Unit))
    {
        this.onCreateView = onCreateView
    }

    /** 添加到父元素 */
    fun addToParent(parent: ViewGroup?, view: View)
    {
        onCreateView?.let { on -> view.on() }
        if (parent == null) return

        var lParams: ViewGroup.LayoutParams? = null
        val margins: Array<Int>
        if (margin != null)
        {
            val m = margin.dist
            margins = arrayOf(m, m, m, m)
        } else
        {
            margins = arrayOf(0, 0, 0, 0)
            if (marginH != null)
            {
                val mH = marginH.dist
                margins[0] = mH
                margins[2] = mH
            }
            if (marginV != null)
            {
                val mV = marginV.dist
                margins[1] = mV
                margins[3] = mV
            }
            if (margins[0] == 0) margins[0] = marginLeft.dist
            if (margins[1] == 0) margins[1] = marginTop.dist
            if (margins[2] == 0) margins[2] = marginRight.dist
            if (margins[3] == 0) margins[3] = marginBottom.dist
        }

        width = width ?: WRAP_CONTENT
        height = height ?: WRAP_CONTENT

        when (parent)
        {
            is FrameLayout ->
            {
                val params = FrameLayout.LayoutParams(width.dist, height.dist)
                layoutGravity?.let { params.gravity = it }
                params.setMargins(margins[0], margins[1], margins[2], margins[3])
                lParams = params
            }
            is LinearLayout ->
            {
                val params = LinearLayout.LayoutParams(width.dist, height.dist)
                layoutGravity?.let { params.gravity = it }
                weight?.let { params.weight = it.toFloat() }
                params.setMargins(margins[0], margins[1], margins[2], margins[3])
                lParams = params
            }
            is FlexboxLayout ->
            {
                val params = FlexboxLayout.LayoutParams(width.dist, height.dist)
                params.setMargins(margins[0], margins[1], margins[2], margins[3])
                alignSelf?.let { params.alignSelf = it }
                flexGrow?.let { params.flexGrow = it.toFloat() }
                flexShrink?.let { params.flexShrink = it.toFloat() }
                flexBasisPercent?.let { params.flexBasisPercent = it.toFloat() }
                isWrapBefore?.let { params.isWrapBefore = it }
                maxHeight?.let { params.maxHeight = it.dist }
                maxWidth?.let { params.maxWidth = it.dist }
                minHeight?.let { params.minHeight = it.dist }
                minWidth?.let { params.minWidth = it.dist }
                order?.let { params.order = it }
                lParams = params
            }
            else ->
            {
                val params = ViewGroup.MarginLayoutParams(width.dist, height.dist)
                params.setMargins(margins[0], margins[1], margins[2], margins[3])
                lParams = params
            }
        }
        parent.addView(view, lParams)
    }

    open fun initUI(context: Context, view: View)
    {
        id?.let { KtUi.addId(it, view) }
        bg?.let {
            if (it is UiShape)
            {
                view.background = it.createDrawable()
            } else if (it is Int)
            {
                view.setBackgroundColor(it)
            } else
            {
                view.bg = it.toString()
            }
        }
        if (padding != null)
        {
            val p = padding.dist
            view.setPadding(p, p, p, p)
        } else
        {
            val p = arrayOf(0, 0, 0, 0)
            if (paddingH != null)
            {
                val pH = paddingH.dist
                p[0] = pH
                p[2] = pH
            }
            if (paddingV != null)
            {
                val pV = paddingV.dist
                p[1] = pV
                p[3] = pV
            }
            if (p[0] == 0) p[0] = paddingLeft.dist
            if (p[1] == 0) p[1] = paddingTop.dist
            if (p[2] == 0) p[2] = paddingRight.dist
            if (p[3] == 0) p[3] = paddingBottom.dist
            view.setPadding(p[0], p[1], p[2], p[3])
        }
        transZ?.let { view.translationZ = it.distFloat }
        alpha?.let { view.alpha = it.toFloat() }
        scaleX?.let { view.scaleX = it.toFloat() }
        scaleY?.let { view.scaleY = it.toFloat() }
        rotation?.let { view.rotation = it.toFloat() }
        visible?.let { view.visibility = if (it) View.VISIBLE else View.GONE }
        focus?.let {
            view.isFocusableInTouchMode = it
            view.isFocusable = it
            if (it && view is EditText)
            {
                view.clearFocus()
                view.requestFocus()
                view.setSelection(view.length())
            }
        }
        corner?.let {
            view.outlineProvider = KtCornerProvider(corner.dist, cornerDirect ?: "", view)
        }
        minWidth?.let { view.minimumWidth = it.dist }
        minHeight?.let { view.minimumHeight = it.dist }
        link?.let { link -> view.setOnClickListener { KtUi.onLink?.invoke(context, link) } }

        onClick?.let { onClick -> view.setOnClickListener { view.onClick() } }
        delayClick?.let { delayClick -> view.setDelayClickListener { view.delayClick() } }

        if (view is KtView) isClick?.let { view.setClick(it) }
    }

    open fun createView(context: Context, parent: ViewGroup? = null): View
    {
        return KtView(context).also()
        {
            initUI(context, it)
            addToParent(parent, it)
        }
    }
}

open class KtView : View
{
    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    {
        initXML(attrs)
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    {
        initXML(attrs)
    }

    private fun initXML(attrs: AttributeSet)
    {
    }

    /********************************************** 点击 ****************************************/

    fun setClick(isClick: Boolean)
    {
        isAlpha = isClick
        isClickable = isClick
    }

    private var isAlpha = false

    override fun dispatchSetPressed(pressed: Boolean)
    {
        if (isAlpha) alpha = if (pressed || !isEnabled) 0.75f else 1f
        super.dispatchSetPressed(pressed)
    }

    override fun setEnabled(enabled: Boolean)
    {
        if (isAlpha) alpha = if (enabled) 1f else 0.75f
        super.setEnabled(enabled)
    }
}

fun Any.ui_View(id: String? = null, block: (UiView.() -> Unit)? = null): UiView
{
    val ui = UiView(id)
    block?.let { ui.it() }
    if (this is UiGroup) addChild(ui)
    return ui
}